package com.hd.trans.widgets

import android.content.Context
import android.util.AttributeSet
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView


class SmartScrollbarRecyclerView(
    context: Context,
    attributeSet: AttributeSet?,
    defaultStyleAttribute: Int
) : RecyclerView(context, attributeSet, defaultStyleAttribute) {

    constructor(
        context: Context,
        attributeSet: AttributeSet
    ) : this(context, attributeSet, 0)

    constructor(
        context: Context
    ) : this(context, null, 0)

    override fun computeVerticalScrollExtent(): Int {
        return checkCalculationPrerequisites(
            onFailure = {
                super.computeVerticalScrollExtent()
            },
            onSuccess = { _, rangeSpan, scrollRange ->

                val extentSpanCount = 1.5F
                val scrollExtent = (extentSpanCount / rangeSpan)

                (scrollExtent * scrollRange).toInt()
            }
        )
    }

    override fun computeVerticalScrollOffset(): Int {
        return checkCalculationPrerequisites(
            onFailure = {
                super.computeVerticalScrollOffset()
            },
            onSuccess = { layoutManager, rangeSpanCount, scrollRange ->

                val firstSpanPosition = calculateFirstVisibleItemPosition(layoutManager)
                val lastSpanPosition = calculateLastVisibleItemPosition(layoutManager)
                val visibleSpanCount = lastSpanPosition - firstSpanPosition

                val remainingSpanCount = rangeSpanCount - 1 - visibleSpanCount

                val partialProgress = (firstSpanPosition / remainingSpanCount)
                val progressSpanPosition = firstSpanPosition + (visibleSpanCount * partialProgress)
                val scrollProgress = progressSpanPosition / rangeSpanCount

                (scrollProgress * scrollRange).toInt()
            }
        )
    }

    private fun calculateFirstVisibleItemPosition(layoutManager: LinearLayoutManager): Int {
        val firstCompletelyVisibleItemPosition = layoutManager.findFirstCompletelyVisibleItemPosition()
        return if (firstCompletelyVisibleItemPosition == -1) {
            layoutManager.findFirstVisibleItemPosition()
        } else {
            firstCompletelyVisibleItemPosition
        }
    }

    private fun calculateLastVisibleItemPosition(layoutManager: LinearLayoutManager): Int {
        val lastCompletelyVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition()
        return if (lastCompletelyVisibleItemPosition == -1) {
            layoutManager.findLastVisibleItemPosition()
        } else {
            lastCompletelyVisibleItemPosition
        }
    }

    private fun checkCalculationPrerequisites(
        onFailure: () -> Int,
        onSuccess: (LinearLayoutManager, Float, Int) -> Int
    ): Int {

        val layoutManager = layoutManager

        if (layoutManager !is LinearLayoutManager) {
            return onFailure.invoke()
        }

        val scrollRange = computeVerticalScrollRange()
        if (scrollRange < height) {
            return 0
        }

        val rangeSpanCount = calculateRangeSpanCount()
        if (rangeSpanCount == 0F) {
            return 0
        }

        return onSuccess.invoke(layoutManager, rangeSpanCount, scrollRange)
    }

    private fun calculateRangeSpanCount(): Float {
        val recyclerAdapter = adapter ?: return 0F
        return recyclerAdapter.itemCount.toFloat()
    }
}